home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / Portable Patmos 1.1 / patmos-src / src / netdb.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-01-19  |  11.5 KB  |  512 lines  |  [TEXT/R*ch]

  1. /*
  2.  * BSD-style socket emulation library for the Mac
  3.  * Original author: Tom Milligan
  4.  * Current author: Charlie Reiman - creiman@ncsa.uiuc.edu
  5.  *
  6.  * This source file is placed in the public domian.
  7.  * Any resemblance to NCSA Telnet, living or dead, is purely coincidental.
  8.  *
  9.  *      National Center for Supercomputing Applications
  10.  *      152 Computing Applications Building
  11.  *      605 E. Springfield Ave.
  12.  *      Champaign, IL  61820
  13.  */
  14.  
  15. /*
  16.  *    Internet name routines that every good unix program uses...
  17.  *
  18.  *        gethostbyname
  19.  *        gethostbyaddr
  20.  *      gethostid
  21.  *        gethostname
  22.  *        getdomainname
  23.  *        inet_addr
  24.  *        inet_ntoa
  25.  *        getservbyname
  26.  *        getprotobyname
  27.  */
  28.  
  29. #ifdef USEDUMP
  30. # pragma load "Socket.dump"
  31. #else
  32. # include <Stdio.h>
  33. # include <Types.h>
  34. # include <Resources.h>
  35. # include <Errors.h>
  36. # include <OSUtils.h>
  37.  
  38. # include <s_types.h>
  39. # include <netdb.h>
  40. # include <neti_in.h>
  41. # include <s_socket.h>
  42. # include <s_time.h>
  43. # include <neterrno.h>
  44.  
  45. # include "sock_str.h"
  46. # include "sock_int.h"
  47. #endif
  48.  
  49. #include <Ctype.h>
  50. #include <a_namesr.h>
  51. #include <s_param.h>
  52. #include <sock_ext.h>
  53.  
  54.  
  55. extern SocketPtr sockets;
  56. extern SpinFn spinroutine;
  57. pascal void DNRDone(struct hostInfo *hostinfoPtr,Boolean *done);
  58.  
  59. int h_errno;
  60.  
  61. /*
  62.  *   Gethostbyname and gethostbyaddr each return a pointer to an
  63.  *   object with the following structure describing an Internet
  64.  *   host referenced by name or by address, respectively. This
  65.  *   structure contains the information obtained from the MacTCP
  66.  *   name server.
  67.  *
  68.  *   struct    hostent 
  69.  *   {
  70.  *        char *h_name;
  71.  *        char **h_aliases;
  72.  *        int  h_addrtype;
  73.  *        int  h_length;
  74.  *        char **h_addr_list;
  75.  *   };
  76.  *   #define   h_addr  h_addr_list[0]
  77.  *
  78.  *   The members of this structure are:
  79.  *
  80.  *   h_name       Official name of the host.
  81.  *
  82.  *   h_aliases    A zero terminated array of alternate names for the host.
  83.  *
  84.  *   h_addrtype   The type of address being  returned; always AF_INET.
  85.  *
  86.  *   h_length     The length, in bytes, of the address.
  87.  *
  88.  *   h_addr_list  A zero terminated array of network addresses for the host.
  89.  *
  90.  *   Error return status from gethostbyname and gethostbyaddr  is
  91.  *   indicated by return of a null pointer.  The external integer
  92.  *   h_errno may then  be checked  to  see  whether  this  is  a
  93.  *   temporary  failure  or  an  invalid  or  unknown  host.  The
  94.  *   routine herror  can  be  used  to  print  an error  message
  95.  *   describing the failure.  If its argument string is non-NULL,
  96.  *   it is printed, followed by a colon and a space.   The  error
  97.  *   message is printed with a trailing newline.
  98.  *
  99.  *   h_errno can have the following values:
  100.  *
  101.  *     HOST_NOT_FOUND  No such host is known.
  102.  *
  103.  *     TRY_AGAIN    This is usually a temporary error and
  104.  *                    means   that  the  local  server  did  not
  105.  *                    receive a response from  an  authoritative
  106.  *                    server.   A  retry at some later time may
  107.  *                    succeed.
  108.  *
  109.  *     NO_RECOVERY    Some unexpected server failure was encountered.
  110.  *                     This is a non-recoverable error.
  111.  *
  112.  *     NO_DATA        The requested name is valid but  does  not
  113.  *                    have   an IP  address;  this  is not  a
  114.  *                    temporary error. This means that the  name
  115.  *                    is known  to the name server but there is
  116.  *                    no address  associated  with  this  name.
  117.  *                    Another type of request to the name server
  118.  *                    using this domain name will result in  an
  119.  *                    answer;  for example, a mail-forwarder may
  120.  *                    be registered for this domain.
  121.  *                    (NOT GENERATED BY THIS IMPLEMENTATION)
  122.  */
  123.  
  124. static struct hostInfo macHost;
  125.  
  126. #define MAXALIASES 0
  127. static char *aliasPtrs[MAXALIASES+1] = {NULL};
  128. static ip_addr *addrPtrs[NUM_ALT_ADDRS+1];
  129.  
  130. static struct hostent  unixHost = 
  131. {
  132.     macHost.cname,
  133.     aliasPtrs,
  134.     AF_INET,
  135.     sizeof(ip_addr),
  136.     (char **) addrPtrs
  137. };
  138.  
  139. struct hostent *
  140. gethostbyname(char *name)
  141. {
  142.     Boolean done;
  143.     int i;
  144.     
  145. #if    NETDB_DEBUG >= 3
  146.     dprintf("gethostbyname: '%s'\n",name);
  147. #endif
  148.  
  149.     sock_init();
  150.  
  151.     for (i=0; i<NUM_ALT_ADDRS; i++)
  152.         macHost.addr[i] = 0;
  153.     done = false;
  154.     if (StrToAddr(name,&macHost,(ResultProcPtr) DNRDone,(char *) &done) == cacheFault)
  155.     {
  156. #if NETDB_DEBUG >= 5
  157.         dprintf("gethostbyname: spinning\n");
  158. #endif
  159.         SPINP(!done,SP_NAME,0L)
  160.  
  161. #if NETDB_DEBUG >= 5
  162.         dprintf("gethostbyname: done spinning\n");
  163. #endif
  164.     }
  165.     switch (macHost.rtnCode)
  166.     {
  167.         case noErr: break;
  168.         
  169.         case nameSyntaxErr:    h_errno = HOST_NOT_FOUND;    return(NULL);
  170.         case cacheFault:    h_errno = NO_RECOVERY;        return(NULL);
  171.         case noResultProc:    h_errno = NO_RECOVERY;        return(NULL);
  172.         case noNameServer:    h_errno = HOST_NOT_FOUND;    return(NULL);
  173.         case authNameErr:    h_errno = HOST_NOT_FOUND;    return(NULL);
  174.         case noAnsErr:        h_errno = TRY_AGAIN;        return(NULL);
  175.         case dnrErr:        h_errno = NO_RECOVERY;        return(NULL);
  176.         case outOfMemory:    h_errno = TRY_AGAIN;        return(NULL);
  177.         case notOpenErr:    h_errno = NO_RECOVERY;        return(NULL);
  178.         default:            h_errno = NO_RECOVERY;        return(NULL);
  179.     }
  180.     
  181. #if NETDB_DEBUG >= 5
  182.     dprintf("gethostbyname: name '%s' addrs %08x %08x %08x %08x\n",
  183.             macHost.cname,
  184.             macHost.addr[0],macHost.addr[1],
  185.             macHost.addr[2],macHost.addr[3]);
  186. #endif
  187.  
  188.     /* was the 'name' an IP address? */
  189.     if (macHost.cname[0] == 0)
  190.     {
  191.         h_errno = HOST_NOT_FOUND;
  192.         return(NULL);
  193.     }
  194.     
  195.     /* for some reason there is a dot at the end of the name */
  196.     i = strlen(macHost.cname) - 1;
  197.     if (macHost.cname[i] == '.')
  198.         macHost.cname[i] = 0;
  199.     
  200.     for (i=0; i<NUM_ALT_ADDRS && macHost.addr[i]!=0; i++)
  201.     {
  202.         addrPtrs[i] = &macHost.addr[i];
  203.     }
  204.     addrPtrs[i] = NULL;
  205.     
  206.     return(&unixHost);
  207. }
  208.  
  209. struct hostent *
  210. gethostbyaddr(ip_addr *addrP,int len,int type)
  211. {
  212. #pragma unused(len)
  213. #pragma unused(type)
  214.     Boolean done;
  215.     int i;
  216.     
  217. #if    NETDB_DEBUG >= 3
  218.     dprintf("gethostbyaddr: %08x\n",*addrP);
  219. #endif
  220.  
  221.     sock_init();
  222.     
  223.     for (i=0; i<NUM_ALT_ADDRS; i++)
  224.         macHost.addr[i] = 0;
  225.     done = false;
  226.     if (AddrToName(*addrP,&macHost,(ResultProcPtr) DNRDone,(char *) &done) == cacheFault)
  227.     {
  228. #if NETDB_DEBUG >= 5
  229.         dprintf("gethostbyaddr: spinning\n");
  230. #endif
  231.  
  232.         SPINP(!done,SP_ADDR,0L)
  233. #if NETDB_DEBUG >= 5
  234.         dprintf("gethostbyaddr: done spinning\n");
  235. #endif
  236.     }
  237.     switch (macHost.rtnCode)
  238.     {
  239.         case noErr: break;
  240.         
  241.         case cacheFault:    h_errno = NO_RECOVERY;        return(NULL);
  242.         case noNameServer:    h_errno = HOST_NOT_FOUND;    return(NULL);
  243.         case authNameErr:    h_errno = HOST_NOT_FOUND;    return(NULL);
  244.         case noAnsErr:        h_errno = TRY_AGAIN;        return(NULL);
  245.         case dnrErr:        h_errno = NO_RECOVERY;        return(NULL);
  246.         case outOfMemory:    h_errno = TRY_AGAIN;        return(NULL);
  247.         case notOpenErr:    h_errno = NO_RECOVERY;        return(NULL);
  248.         default:            h_errno = NO_RECOVERY;        return(NULL);
  249.     }
  250. #if NETDB_DEBUG >= 5
  251.     dprintf("gethostbyaddr: name '%s' addrs %08x %08x %08x %08x\n",
  252.             macHost.cname,
  253.             macHost.addr[0],macHost.addr[1],
  254.             macHost.addr[2],macHost.addr[3]);
  255. #endif
  256.     /* for some reason there is a dot at the end of the name */
  257.     i = strlen(macHost.cname) - 1;
  258.     if (macHost.cname[i] == '.')
  259.         macHost.cname[i] = 0;
  260.     
  261.     for (i=0; i<NUM_ALT_ADDRS; i++)
  262.     {
  263.         addrPtrs[i] = &macHost.addr[i];
  264.     }
  265.     addrPtrs[NUM_ALT_ADDRS] = NULL;
  266.     
  267.     return(&unixHost);
  268. }
  269.  
  270. char *
  271. inet_ntoa(ip_addr inaddr)
  272. {
  273.     sock_init();
  274.     
  275.     (void) AddrToStr(inaddr,macHost.cname);
  276.     return(macHost.cname);
  277. }
  278.  
  279. ip_addr 
  280. inet_addr(char *address)
  281. {
  282. #ifndef JAE
  283. OSErr retval;
  284. #endif
  285.     sock_init();
  286. #ifndef JAE
  287.     if ((retval = StrToAddr(address,&macHost,NULL,NULL)) != noErr)
  288. #else
  289.  
  290.  
  291.     if (StrToAddr(address,&macHost,NULL,NULL) != noErr)
  292. #endif
  293.         return((ip_addr)-1);
  294.     
  295. #if NETDB_DEBUG >= 5
  296.     dprintf("inet_addr: name '%s' addr %08x\n",
  297.             macHost.cname,macHost.addr[0]);
  298. #endif
  299.  
  300.     /* was the 'address' really a name? */
  301.     if (macHost.cname[0] != 0)
  302.         return((ip_addr)-1);
  303.     
  304.     return(macHost.addr[0]);
  305. }
  306.  
  307. /*
  308.  * gethostid()
  309.  *
  310.  * Get Internet address. If the application can get by with just
  311.  * this, it avoids the muss and fuss of DNR.
  312.  */
  313.  
  314. unsigned long gethostid()
  315. {
  316.     ip_addr ipaddr;
  317.     
  318.     ipaddr = xIPAddr();
  319.     
  320.     return ((unsigned long) ipaddr);
  321. }
  322.  
  323. /*
  324.  * gethostname()
  325.  *
  326.  * Try to get my host name from DNR. If it fails, just return my
  327.  * IP address as ASCII. This is non-standard, but it's a mac,
  328.  * what do you want me to do?
  329.  */
  330.  
  331. gethostname( machname, buflen)
  332.     char *machname;
  333.     long buflen;
  334. {
  335.     ip_addr ipaddr;
  336.     struct    hostent *hp;
  337.     
  338. #if    NETDB_DEBUG >= 3
  339.     dprintf("gethostname: \n");
  340. #endif
  341.  
  342.     sock_init();        /* initialize the socket stuff. */
  343.     ipaddr = xIPAddr();
  344.     hp = gethostbyaddr( &ipaddr, sizeof(ip_addr), AF_INET);
  345.     if( hp == NULL) 
  346.         sprintf (machname, "%d.%d.%d.%d",ipaddr>>24,
  347.                                 ipaddr>>16 & 0xff,
  348.                                 ipaddr>>8 & 0xff,
  349.                                 ipaddr & 0xff);
  350.     else
  351.         strncpy( machname, hp->h_name, buflen);
  352.     
  353.     machname[buflen-1] = 0;  /* extra safeguard */
  354.     return(0);
  355. }
  356.  
  357.  
  358. /*
  359.  *    getservbybname()
  360.  *
  361.  *    Real kludgy.  Should at least consult a resource file as the service
  362.  *    database.
  363.  */
  364. typedef struct services {
  365.     char        sv_name[12];
  366.     short        sv_number;
  367.     char        sv_protocol[5];
  368. } services_t, *services_p;
  369.  
  370. static    struct services    slist[] = 
  371.     {"echo", 7, "udp"},
  372.     {"discard", 9, "udp"},
  373.     {"time", 37, "udp"},
  374.     {"domain", 53, "udp"},
  375.     {"sunrpc", 111, "udp"},
  376.     {"tftp", 69, "udp"},
  377.     {"biff", 512, "udp"},
  378.     {"who", 513, "udp"},
  379.     {"talk", 517, "udp"},
  380.     {"route", 520, "udp"},
  381.     {"new-rwho", 550, "udp"},
  382.     {"netstat", 15, "tcp"},
  383.     {"ftp-data", 20, "tcp"},
  384.     {"ftp", 21, "tcp"},
  385.     {"telnet", 23, "tcp"},
  386.     {"smtp", 25, "tcp"},
  387.     {"time", 37, "tcp"},
  388.     {"whois", 43, "tcp"},
  389.     {"domain", 53, "tcp"},
  390.     {"hostnames", 101, "tcp"},
  391.     {"nntp", 119, "tcp"},
  392.     {"finger", 79, "tcp"},
  393.     {"uucp-path", 117, "tcp"},
  394.     {"untp", 119, "tcp"},
  395.     {"ntp", 123, "tcp"},
  396.     {"exec", 512, "tcp"},
  397.     {"login", 513, "tcp"},
  398.     {"shell", 514, "tcp"},
  399.     {"printer", 515, "tcp"},
  400.     {"courier", 530, "tcp"},
  401.     {"uucp", 540, "tcp"},
  402.     {"", 0, "" }
  403. };
  404.                      
  405. #define    MAX_SERVENT            10
  406. static     struct servent        servents[MAX_SERVENT];
  407. static     int                    servent_count=0;
  408.  
  409. struct servent *
  410. getservbyname (name, proto)
  411. char        *name, *proto;
  412. {
  413.     int                i;
  414.     struct    servent    *se;
  415.     
  416.     if (strcmp (proto, "udp") == 0 || strcmp (proto, "tcp") == 0) 
  417.     {
  418.         for (i=0; slist[i].sv_number != 0; i++)
  419.             if (strcmp (slist[i].sv_name, name) == 0)
  420.                 if (strcmp (slist[i].sv_protocol, proto) == 0) 
  421.                 {
  422.                     se = &servents[servent_count];
  423.                     se->s_name = slist[i].sv_name;
  424.                     se->s_aliases = NULL;
  425.                     se->s_port = slist[i].sv_number;
  426.                     se->s_proto = slist[i].sv_protocol;
  427.                     servent_count = (servent_count +1) % MAX_SERVENT;
  428.                     return (se);
  429.                 }
  430.         return (NULL);
  431.     }
  432.     else 
  433.     {
  434.         errno = errno_long = EPROTONOSUPPORT;
  435.         return(NULL);
  436.     }
  437. }
  438.  
  439. static    char    tcp[] = "tcp";
  440. static    char    udp[] = "udp";
  441. #define    MAX_PROTOENT            10
  442. static     struct protoent        protoents[MAX_PROTOENT];
  443. static     int                    protoent_count=0;
  444. struct protoent *
  445. getprotobyname (name)
  446. char        *name;
  447. {
  448.     struct protoent *pe;
  449.     
  450.     pe = &protoents[protoent_count];
  451.     if (strcmp (name, "udp") == 0) 
  452.     {
  453.         pe->p_name = udp;
  454.         pe->p_proto = IPPROTO_UDP;
  455.     }
  456.     else if (strcmp (name, "tcp") == 0) 
  457.     {
  458.         pe->p_name = tcp;
  459.         pe->p_proto = IPPROTO_TCP;
  460.     }
  461.     else 
  462.     {    
  463.         errno = errno_long = EPROTONOSUPPORT;
  464.         return(NULL);
  465.     }
  466.     pe->p_aliases = NULL;
  467.     protoent_count = (protoent_count +1) % MAX_PROTOENT;
  468.     return (pe);
  469. }
  470.  
  471. char *h_errlist[] = 
  472. {
  473.     "Error 0",
  474.     "Unknown host",                        /* 1 HOST_NOT_FOUND */
  475.     "Host name lookup failure",            /* 2 TRY_AGAIN */
  476.     "Unknown server error",                /* 3 NO_RECOVERY */
  477.     "No address associated with name",    /* 4 NO_ADDRESS */
  478. };
  479.  
  480. const int    h_nerr = { sizeof(h_errlist)/sizeof(h_errlist[0]) };
  481.  
  482. #ifdef HERROR
  483.  
  484. void herror(char *s)
  485.     {
  486.     fprintf(stderr,"%s: ",s);
  487.     if (h_errno < h_nerr)
  488.         fprintf(stderr,h_errlist[h_errno]);
  489.     else
  490.         fprintf(stderr,"error %d",h_errno);
  491.     fprintf(stderr,"\n");
  492.     }
  493.  
  494. #endif
  495.  
  496. char *herror_str(int theErr) {
  497.     if (theErr > h_nerr )
  498.         return NULL;
  499.     else
  500.         return h_errlist[theErr];
  501.         }
  502.  
  503. #pragma segment SOCK_RESIDENT
  504. pascal void DNRDone(hostinfoPtr,done)
  505.     struct hostInfo *hostinfoPtr;
  506.     Boolean *done;
  507. {
  508. #pragma unused(hostinfoPtr)
  509.     *done = true;
  510. }
  511.